Создание и редактирование записей
=================================

После того, как мы закончили с моделью `Post`, займёмся контроллером
`PostController` и его отображениями. В данном разделе мы настроим правила
доступа операций CRUD. Затем изменим код, отвечающий за `создание`(`create`) и
`обновление`(`update`).

Настройка правил доступа
------------------------

Первое, что мы запланировали — настройка
[прав доступа](/doc/guide/ru/topics.auth#access-control-filter). Код,
сгенерированный при помощи `gii` нам не подойдёт.

Необходимо изменить метод `accessRules()` в файле
`/wwwroot/blog/protected/controllers/PostController.php` следующим образом:

~~~
[php]
public function accessRules()
{
	return array(
		array('allow',  // позволим всем пользователям выполнять действия 'list' и 'show'
			'actions'=>array('index', 'view'),
			'users'=>array('*'),
		),
		array('allow', // позволим аутентифицированным пользователям выполнять любые действия
			'users'=>array('@'),
		),
		array('deny',  // остальным запретим всё
			'users'=>array('*'),
		),
	);
}
~~~

Описанные выше правила разрешают всем пользователям выполнять действия
`index` и `view`. Аутентифицированным — любые действия, включая `admin`.
Всем остальным пользователям запрещено всё. Стоит отметить, что правила
применяются в порядке их описания. Первое сработавшее правило определяет,
давать доступ или не давать. К примеру, если текущий пользователь является
владельцем системы и пытается зайти на страницу создания записи, будет применено
второе правило и доступ будет разрешён.


Правки в действиях `create` и `update`
--------------------------------------

Операции `create` и `update` довольно похожи. В обоих случаях требуется
вывести HTML форму для сбора данных, вводимых пользователем. Также требуется
валидация и сохранение данных в БД. Главное отличие в том, что при `update`
форма будет заполняться данными о редактируемой записи. По этой причине `gii`
генерирует вложенное отображение `/wwwroot/blog/protected/views/post/_form.php`,
которое включается как в отображение `create`, так и отображение `update` для
вывода HTML формы.

Для начала изменим файл `_form.php` таким образом, чтобы форма собирала только
нужные нам данные: `title`, `content`, `tags` и `status`. Для первых трёх атрибутов мы
используем текстовые поля. Для `status` — выпадающий список со всеми возможными
состояниями записи:

~~~
[php]
<?php echo $form->dropDownList($model,'status',Lookup::items('PostStatus')); ?>
~~~

В приведённом коде для получения списка статусов используется вызов `Lookup::items('PostStatus')`.

Далее изменим класс `Post` таким образом, чтобы он автоматически выставлял
некоторые атрибуты (такие, как `create_time` и `author_id`) непосредственно перед
сохранением записи в БД. Перекроем метод `beforeSave()`:

~~~
[php]
protected function beforeSave()
{
	if(parent::beforeSave())
	{
		if($this->isNewRecord)
		{
			$this->create_time=$this->update_time=time();
			$this->author_id=Yii::app()->user->id;
		}
		else
			$this->update_time=time();
		return true;
	}
	else
		return false;
}
~~~

При сохранении записи мы хотим также обновить информацию о частоте использования
тегов в таблице `tbl_tag`. Мы можем реализовать это в методе `afterSave()`,
который автоматически вызывается после успешного сохранения записи в БД.

~~~
[php]
protected function afterSave()
{
	parent::afterSave();
	Tag::model()->updateFrequency($this->_oldTags, $this->tags);
}

private $_oldTags;

protected function afterFind()
{
	parent::afterFind();
	$this->_oldTags=$this->tags;
}
~~~

Так как необходимо определить, менял ли пользователь теги при редактировании
записи, нам понадобятся старые теги. Для этого мы реализуем метод
`afterFind()`, который записывает старые теги в свойство `_oldTags`. Метод
`afterFind()` вызывается автоматически при заполнении модели AR данными, полученными
из БД.

Здесь мы не будем детально рассматривать метод `Tag::updateFrequency()`.
Заинтересованные читатели могут ознакомиться с ним в файле
`/wwwroot/yii/demos/blog/protected/models/Tag.php`.